package com.haircut.project.service.category.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.haircut.project.dao.category.ProjectCategoryMapper;
import com.haircut.project.dao.config.ProjectConfigMapper;
import com.haircut.project.model.category.ProjectCategory;
import com.haircut.project.model.config.ProjectConfig;
import com.haircut.project.service.category.ICategoryService;
import com.haircut.project.utils.category.CategoryUtils;
import com.haircut.project.vo.catetory.CateTreeVo;
import com.haircut.project.vo.catetory.CategoryOptVo;
import com.haircut.project.vo.catetory.CategoryTreeVo;
import com.haircut.project.vo.catetory.CategoryVo;
import com.haircut.sys.constant.Constants;
import com.haircut.sys.utils.user.SecurityUtils;
import com.haircut.sys.vo.user.LoginUserVo;
import com.modular.constant.BaseCodeDesc;
import com.modular.constant.NumberConstant;
import com.modular.enums.DataStts;
import com.modular.exception.ModularException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class CategoryServiceImpl implements ICategoryService {
    @Autowired
    private ProjectCategoryMapper projectCategoryMapper;
    @Autowired
    private ProjectConfigMapper projectConfigMapper;
    @Autowired
    @Qualifier("modularSnowflake")
    private Snowflake snowflake;
    /**
     * 查询分类列表
     * @return
     */
    @Override
    public List<CategoryTreeVo> findAll()
    {
        return CategoryUtils.coverTree(projectCategoryMapper.findAll());
    }

    /**
     * 查询分类列表
     * @return
     */
    @Override
    public List<CateTreeVo> findTree()
    {
        return CategoryUtils.coverTreeVo(projectCategoryMapper.findAll());
    }
    /**
     * 新增分类
     * @param optVo
     */
    @Override
    public void saveCategory(CategoryOptVo optVo)
    {
        // 判断分类是否名称是否相同
        checkExsitCateName(optVo.getCategoryName(), null);
        int catLevel = NumberConstant.ZERO;
        if(ObjectUtil.notEqual(optVo.getParentId(), Constants.DEFAULT_PARENT_ID)){
            ProjectCategory parentCategory = projectCategoryMapper.selectById(optVo.getParentId());
            if(ObjectUtil.isNull(parentCategory)){
                throw new ModularException(BaseCodeDesc.DEFATUL_MSG,"上级分类信息错误");
            }
            catLevel = parentCategory.getCatLevel();
        }
        catLevel ++;
        if(catLevel > NumberConstant.TWO){
            throw new ModularException(BaseCodeDesc.DEFATUL_MSG,"分类不能超过2级");
        }

        LoginUserVo loginUserVo = SecurityUtils.getLoginUser();
        Date currDate = DateUtil.date();
        ProjectCategory category = new ProjectCategory();
        BeanUtils.copyProperties(optVo,category);
        category.setSortNum(Optional.ofNullable(category.getSortNum()).orElse(NumberConstant.ZERO));
        category.setDataStts(DataStts.ENABLED.getCode());
        category.setCatLevel(catLevel);
        category.setCreateDate(currDate);
        category.setModifyDate(currDate);
        category.setCreateUserId(loginUserVo.getUserId());
        category.setModifyUserId(loginUserVo.getUserId());
        category.setId(snowflake.nextIdStr());
        projectCategoryMapper.insert(category);
    }

    /**
     * 修改分类
     * @param optVo
     */
    @Override
    public void modifyCategory(CategoryOptVo optVo)
    {
        if(StrUtil.isBlank(optVo.getId())){
            throw new ModularException(BaseCodeDesc.DEFATUL_MSG,"分类id必须填写");
        }
        ProjectCategory category = projectCategoryMapper.selectById(optVo.getId());
        if(ObjectUtil.isNull(category)){
            throw new ModularException(BaseCodeDesc.DEFATUL_MSG,"分类信息错误");
        }
        // 判断分类是否名称是否相同
        checkExsitCateName(optVo.getCategoryName(), optVo.getId());
        Date currDate = DateUtil.date();
        String userId = SecurityUtils.getUserId();
        LambdaUpdateWrapper<ProjectCategory> modify = Wrappers.lambdaUpdate();
        modify.set(ProjectCategory::getModifyDate,currDate).set(ProjectCategory::getModifyUserId,userId);
        modify.set(ProjectCategory::getCategoryName,optVo.getCategoryName()).set(ProjectCategory::getParentId,optVo.getParentId());
        modify.set(ProjectCategory::getSortNum,Optional.ofNullable(optVo.getSortNum()).orElse(NumberConstant.ONE));
        modify.eq(ProjectCategory::getId,optVo.getId());
        projectCategoryMapper.update(modify);
    }

    /**
     * 删除分类
     * @param id
     */
    @Override
    public void delCategory(String id)
    {
        if(StrUtil.isBlank(id)){
            throw new ModularException(BaseCodeDesc.DEFATUL_MSG,"分类id必须填写");
        }
        ProjectCategory category = projectCategoryMapper.selectById(id);
        if(ObjectUtil.isNull(category)){
            throw new ModularException(BaseCodeDesc.DEFATUL_MSG,"分类信息错误");
        }
        LambdaQueryWrapper<ProjectCategory> query = Wrappers.lambdaQuery();
        query.eq(ProjectCategory::getParentId,category.getId());
        Long count = projectCategoryMapper.selectCount(query);
        if(ObjectUtil.isNotNull(count) && count > NumberConstant.LONG_ZERO){
            throw new ModularException(BaseCodeDesc.DEFATUL_MSG,"有下级分类，不能删除");
        }
        LambdaQueryWrapper<ProjectConfig> configQuery = Wrappers.lambdaQuery();
        configQuery.eq(ProjectConfig::getCategoryId,category.getId());
        count = projectConfigMapper.selectCount(configQuery);
        if(ObjectUtil.isNotNull(count) && count > NumberConstant.LONG_ZERO){
            throw new ModularException(BaseCodeDesc.DEFATUL_MSG,"分类下有项目，不能删除");
        }
        projectCategoryMapper.deleteById(id);
    }

    /**
     * 查询分类名称是否重复
     * @param categoryName
     * @param id
     */
    private void checkExsitCateName(String categoryName,String id){
        LambdaQueryWrapper<ProjectCategory> query = Wrappers.lambdaQuery();
        query.eq(ProjectCategory::getCategoryName,categoryName);
        if(StrUtil.isNotBlank(id)){
            query.ne(ProjectCategory::getId,id);
        }
        Long count = projectCategoryMapper.selectCount(query);
        count = Optional.ofNullable(count).orElse(NumberConstant.LONG_ZERO);
        if(count > NumberConstant.LONG_ZERO){
            throw new ModularException(BaseCodeDesc.DEFATUL_MSG,"同一级别分类名称不能相同");
        }
    }

    /**
     * 根据分类查询上级id
     * @param parentId
     * @return
     */
    @Override
    public List<CategoryVo> findParentId(String parentId)
    {
        LambdaQueryWrapper<ProjectCategory> query = Wrappers.lambdaQuery();
        query.eq(ProjectCategory::getParentId,parentId);
        List<ProjectCategory> list = projectCategoryMapper.selectList(query);
        if(CollUtil.isEmpty(list)){
            return Collections.emptyList();
        }
        List<CategoryVo> categoryVoList = new ArrayList<>(list.size());
        CategoryVo categoryVo = null;
        for(ProjectCategory category:list){
            categoryVo = new CategoryVo();
            BeanUtils.copyProperties(category,categoryVo);
            categoryVoList.add(categoryVo);
        }
        return categoryVoList;
    }

    /**
     * 根据id查询分类信息
     * @param idList
     * @return
     */
    @Override
    public Map<String,CategoryVo> findByIdList(List<String> idList)
    {
        List<ProjectCategory> categoryList = projectCategoryMapper.selectBatchIds(idList);
        if(CollUtil.isEmpty(categoryList)){
            return Collections.emptyMap();
        }
        return categoryList.stream().collect(Collectors.toMap(ProjectCategory::getId,p->{
            CategoryVo categoryVo = new CategoryVo();
            BeanUtils.copyProperties(p,categoryVo);
            return categoryVo;
        }));
    }

}
